package com.wedo.user.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wedo.common.pojo.PageResult;
import com.wedo.common.utils.NumberUtils;
import com.wedo.user.mapper.UserMapper;
import com.wedo.user.pojo.RequestUser;
import com.wedo.user.pojo.User;
import com.wedo.user.utils.CodecUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.awt.print.Book;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final String KEY_LOGIN_PREFIX = "user:verify:";

    /**
     * 检验用户名或手机号是否存在
     * @param data
     * @param type
     * @return
     */
    public Boolean checkUser(String data, Integer type) {
        User record = new User();
        if (type == 1) {
            record.setUsername(data);
        } else if (type == 2) {
            record.setPhone(data);
        } else {
            return null;
        }
        return this.userMapper.selectCount(record) == 0;
    }


    public void sendVerifyCode(String phone) {
        if (StringUtils.isBlank(phone)) {
            return;
        }

        // 生成验证码
        String code = NumberUtils.generateCode(6);

        // 发送消息到rabbitMQ
        Map<String, String> msg = new HashMap<>();
        msg.put("phone",phone);
        msg.put("code",code);
        this.amqpTemplate.convertAndSend("WEDO.SMS.EXCHANGE","verifycode.sms",msg);

        // 将验证码保存到redis中
        // 如果是登录验证码
        redisTemplate.opsForValue().set(KEY_LOGIN_PREFIX + phone,code,5, TimeUnit.MINUTES);
    }

    public Boolean register(User user, String code) {
        if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPhone())) {
            return false;
        }
        // 如果用户名和手机号都已经存在
        if (!checkUser(user.getUsername(),1) || !checkUser(user.getPhone(),2)) {
            return false;
        }
        // 查询redis中的验证码
        String redisCode = this.redisTemplate.opsForValue().get(KEY_LOGIN_PREFIX + user.getPhone());

        // 1.校验验证码
        if (!StringUtils.equals(code,redisCode)) {
            return false;
        }

        // 2.生成盐
        String salt = CodecUtils.generateSalt();
        user.setSalt(salt);

        // 3.加盐加密
        user.setPassword(CodecUtils.md5Hex(user.getPassword(), salt));

        // 4.新增用户
        user.setId(null);
        this.userMapper.insertSelective(user);
        return true;
    }

    public User queryByUsernameAndPassword(String username,String password) {
        User record = new User();
        record.setUsername(username);
        User result = this.userMapper.selectOne(record);

        // 判断user是否为空
        if (result == null) {
            return registerByUsername(username,password);
        }

        // 获取盐并加密
        password = CodecUtils.md5Hex(password,result.getSalt());

        // 和数据库中的密码比较
        if (StringUtils.equals(password,result.getPassword())) {
            result.setPassword(null);
            return result;
        }
        return null;
    }

    private User registerByUsername(String username, String password) {
        if (StringUtils.isBlank(username)) {
            return null;
        }

        if (!checkUser(username,1)) {
            return null;
        }

        User user = new User();
        user.setUsername(username);
        user.setNickname("未设置昵称");

        // 1.生成盐
        String salt = CodecUtils.generateSalt();
        user.setSalt(salt);

        // 2.加盐加密
        user.setPassword(CodecUtils.md5Hex(password, salt));

        // 3.新增用户
        user.setId(null);
        this.userMapper.insertSelective(user);
        return user;

    }

    public User queryByPhoneAndCode(String phone,String code) {
        // 查询redis中的验证码
        String redisCode = this.redisTemplate.opsForValue().get(KEY_LOGIN_PREFIX + phone);

        // 判断验证码是否相同
        if (!StringUtils.equals(redisCode,code)) {
            return null;
        }
        this.redisTemplate.delete(KEY_LOGIN_PREFIX + phone);
        User user = new User();
        user.setPhone(phone);
        user = this.userMapper.selectOne(user);
        if (user == null) {
            // 根据手机号码注册
            return registerByPhone(phone);
        }
        user.setPassword(null);
        return user;
    }

    private User registerByPhone(String phone) {
        User user = new User();
        user.setPhone(phone);
        user.setCreated(new Date());
        user.setNickname("未设置昵称");
        user.setId(null);
        this.userMapper.insertSelective(user);
        return user;
    }

    public void updatePhoto(User user) {
        User u = new User();
        u.setId(user.getId());
        u.setuPhoto(user.getuPhoto());
        this.userMapper.updateByPrimaryKeySelective(u);
    }

    public void updateNickname(User user) {
        User u = new User();
        u.setId(user.getId());
        u.setNickname(user.getNickname());
        this.userMapper.updateByPrimaryKeySelective(u);
    }

    public User updatePhone(RequestUser user) {
        // 校验手机号是否存在
        if (!checkUser(user.getPhone(),2)) {
            return null;
        }

        // 查询redis中的验证码
        String redisCode = this.redisTemplate.opsForValue().get(KEY_LOGIN_PREFIX + user.getPhone());

        // 判断验证码是否相同
        if (!StringUtils.equals(redisCode,user.getCode())) {
            return null;
        }

        User u = new User();
        u.setId(user.getId());
        u.setPhone(user.getPhone());
        this.userMapper.updateByPrimaryKeySelective(u);
        u.setPassword(null);
        return u;
    }

    public User updatePassword(User user) {
        User u = new User();
        u.setId(user.getId());

        // 1.生成盐
        String salt = CodecUtils.generateSalt();
        u.setSalt(salt);

        // 2.加盐加密
        u.setPassword(CodecUtils.md5Hex(user.getPassword(), salt));

        this.userMapper.updateByPrimaryKeySelective(u);
        u.setPassword(null);
        return u;
    }

    public User queryByUserId(Long id) {
        User user = this.userMapper.selectByPrimaryKey(id);
        user.setPassword(null);
        user.setSalt(null);
        return user;
    }

    /**
     * 分页查询用户
     * @param username
     * @param phone
     * @param nickname
     * @param page
     * @param rows
     * @return
     */
    public PageResult<User> queryUsersByPage(String username, String phone,String nickname, Integer page, Integer rows) {
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();

        // 不查询密码和盐
        example.excludeProperties("password","salt");

        // 添加查询条件
        if (StringUtils.isNotBlank(username)) {
            criteria.andLike("username", "%" + username + "%");
        }
        if (StringUtils.isNotBlank(phone)) {
            criteria.andEqualTo("phone", phone);
        }
        if (StringUtils.isNotBlank(nickname)) {
            criteria.andEqualTo("nickname","%" + nickname + "%");
        }

        // 添加分页
        PageHelper.startPage(page, rows);
        List<User> users = this.userMapper.selectByExample(example);

        PageInfo<User> pageInfo = new PageInfo<>(users);

        return new PageResult<>(pageInfo.getTotal(),pageInfo.getPages(), users);

    }

    public Boolean deleteUser(Long id) {
        return this.userMapper.deleteByPrimaryKey(id) > 0;
    }
}
